package topcbl.game;

import java.util.HashMap;

import topcbl.gamewithme.R;
import topcbl.room.MainActivity;
import topcbl.room.Player;
import topcbl.room.Room;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class DominoActivity extends Activity {
	// thread
	ServerDomino mServerDomino = null;
	ClientDomino mClientDomino = null;
	Handler handler = new Handler();
	// view
	DominoChessBoard mChessBoard;
	Button btnExitGame, btnDropTurn;
	ViewGroup groupBtnBlock;
	ImageView[] arrBlockOnHand = new ImageView[7];
	// data
	int mNumberBlockOnHand = 0;
	int mNumberDropTurn = 0;
	String updateData = "";
	public static final int IMAGE_BLOCK_SET[] = { R.drawable.block0_0,
			R.drawable.block0_1, R.drawable.block0_2, R.drawable.block0_3,
			R.drawable.block0_4, R.drawable.block0_5, R.drawable.block0_6,
			R.drawable.block1_1, R.drawable.block1_2, R.drawable.block1_3,
			R.drawable.block1_4, R.drawable.block1_5, R.drawable.block1_6,
			R.drawable.block2_2, R.drawable.block2_3, R.drawable.block2_4,
			R.drawable.block2_5, R.drawable.block2_6, R.drawable.block3_3,
			R.drawable.block3_4, R.drawable.block3_5, R.drawable.block3_6,
			R.drawable.block4_4, R.drawable.block4_5, R.drawable.block4_6,
			R.drawable.block5_5, R.drawable.block5_6, R.drawable.block6_6 };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_domino);
		System.gc();
		if (MainActivity.mServer != null) { // player is server
			mServerDomino = new ServerDomino();
			mServerDomino.start();
		} else { // player is client
			mClientDomino = new ClientDomino();
			mClientDomino.start();
		}
		initView();
	}

	private void initView() {
		mChessBoard = (DominoChessBoard) findViewById(R.id.gameView);
		btnExitGame = (Button) findViewById(R.id.domino_back);
		btnDropTurn = (Button) findViewById(R.id.domino_drop);
		groupBtnBlock = (ViewGroup) findViewById(R.id.domino_block_set);
		int[] listResource = { R.id.domino_block1, R.id.domino_block2,
				R.id.domino_block3, R.id.domino_block4, R.id.domino_block5,
				R.id.domino_block6, R.id.domino_block7 };
		for (int i = 0; i < arrBlockOnHand.length; i++) {
			arrBlockOnHand[i] = (ImageView) findViewById(listResource[i]);
			arrBlockOnHand[i].setTag(i);
			arrBlockOnHand[i].setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					mChessBoard.mChoosingBlock = (int) v.getTag();
				}
			});
		}
		btnExitGame.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				finish();
			}
		});
		btnDropTurn.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				if (MainActivity.mServer != null) {
					// identify that all player can't play anymore and game
					// should be
					// finish by count point
					if (mNumberDropTurn == MainActivity.mServer.getRoom()
							.getNumberOfPlayer() - 1) {
						finishGameByCountPoint();
					} else {
						MainActivity.mServer.getRoom().send2AllPlayer(
								"DROP_TURN"); // not need, just for future
						mServerDomino.wakeUpThead();
					}
				} else {
					MainActivity.mClient.getOutput().println("DROP_TURN");
				}
			}
		});
	}

	public void removeBlockBtn(int choosingBlock) {
		groupBtnBlock.removeView(arrBlockOnHand[choosingBlock]);
	}

	/**
	 * Ánh xạ hashMap vào bảng lưu trữ tài nguyên
	 * 
	 * @param blockInFo
	 *            hashMap chứa thông tin về 1 block
	 * @return Id tài nguyên trả về
	 */
	public int getBlockImage(HashMap<String, Integer> blockInFo) {
		int first = blockInFo.get("1st");
		int second = blockInFo.get("2nd");
		int position = 0;
		for (int i = 0; i < first; i++) {
			position += 7 - i;
		}
		return IMAGE_BLOCK_SET[position + second - first];
	}

	public static int getBlockImage(int first, int second) {
		int position = 0;
		for (int i = 0; i < first; i++) {
			position += 7 - i;
		}
		return IMAGE_BLOCK_SET[position + second - first];
	}

	public void finishGameByCountPoint() {
		Room room = MainActivity.mServer.getRoom();
		room.send2AllPlayer("COUNT_POINT");
		// mặc định server win, lấy point server làm mốc
		int winner = 0, point = mChessBoard.countPoint();
		int numberPlayers = room.getNumberOfPlayer();
		try {
			for (int i = 1; i < numberPlayers; i++) {
				// if player belong team left
				if (i < numberPlayers / 2) {
					int enemyPoint = Integer.parseInt(room.getLeftPlayer(i)
							.receiveMessage());
					if (point > enemyPoint) {
						winner = i;
						point = enemyPoint;
					}
				} else { // belong team right
					int enemyPoint = Integer.parseInt(room.getRightPlayer(
							i % 2 - 1).receiveMessage());
					if (point > enemyPoint) {
						winner = i;
						point = enemyPoint;
					}
				}
			}
			// notify win to player who is lowest score
			room.refresh();
			if (winner == 0) { // server win
				Toast.makeText(DominoActivity.this,
						"Thắng với điểm số: " + point + " ..Gratz!",
						Toast.LENGTH_LONG).show();
				room.send2AllPlayer("LOSE_0");
				mServerDomino.interrupt();
			} else { // client win
				Player winnerPlayer;
				if (winner < numberPlayers / 2)
					winnerPlayer = room.getLeftPlayer(winner);
				else
					winnerPlayer = room.getRightPlayer(winner % 2 - 1);
				winnerPlayer.sendMessage("WIN_0");
				room.send2AllPlayerWithout1("LOSE_0", winnerPlayer);
				Toast.makeText(DominoActivity.this,
						"Bạn đã thua vì có điểm cao hơn!", Toast.LENGTH_LONG)
						.show();
				mServerDomino.interrupt();
			}

		} catch (Exception e) {
			Log.wtf("topcbl", e.getMessage());
		}
	}

	// ==========================================================================

	class ServerDomino extends Thread {
		Boolean pause = true; // variable just use for pause thread

		@Override
		public void run() {
			try {
				MainActivity.mServer.getRoom().refresh();
				chiaBai();
				// điều tiết người chơi lần lượt đánh
				Player curPlayer;
				int cur = 0;
				String data;
				while (!isInterrupted()) {
					if (cur >= MainActivity.mServer.getRoom()
							.getNumberOfPlayer() / 2) {
						cur = 0;
					}
					curPlayer = MainActivity.mServer.getRoom().getLeftPlayer(
							cur);
					if (curPlayer.isServer()) { // case server play
						handler.post(new Runnable() {
							@Override
							public void run() {
								mChessBoard.mCanPlay = true;
							}
						});
						synchronized (pause) {
							pause.wait();
						}
					} else { // case client left team play
						curPlayer.sendMessage("CAN_PLAY");
						data = curPlayer.receiveMessage();
						MainActivity.mServer.getRoom().send2AllPlayerWithout1(
								data, curPlayer);
						handleMessageOnServer(data);
					}
					// case client right team play
					curPlayer = MainActivity.mServer.getRoom().getRightPlayer(
							cur);
					curPlayer.sendMessage("CAN_PLAY");
					data = curPlayer.receiveMessage();
					MainActivity.mServer.getRoom().send2AllPlayerWithout1(data,
							curPlayer);
					handleMessageOnServer(data);
					cur++;
				}
			} catch (Exception e) {
				Log.i("topcbl", "Server xảy ra lỗi: " + e.getMessage());
			}
		}

		public void wakeUpThead() {
			synchronized (pause) {
				pause.notify();
			}
		}

		public void handleMessageOnServer(String dataReceived) {
			String dataSplit[] = dataReceived.split("_");
			String code = dataSplit[0];
			String data = dataSplit[1];
			updateData = data;
			switch (code) {
			case "FIRSTPLAY":
				handler.post(new Runnable() {
					@Override
					public void run() {
						mChessBoard.putFirstBlockOnChessBoard(updateData);
					}
				});
				break;
			case "PLAY":
				handler.post(new Runnable() {
					@Override
					public void run() {
						mChessBoard.putOnChessBoard(updateData);
						// reset count drop when any player play
						mNumberDropTurn = 0;
					}
				});
				break;
			case "LOSE":
				Toast.makeText(DominoActivity.this, "Bạn đã thua :(",
						Toast.LENGTH_LONG).show();
				this.interrupt();
			case "DROP":
				mNumberDropTurn++;
			default:
			}

		}

		public void chiaBai() {
			// tạo bộ bài 28 quân 56 số ban đầu
			int k = 0;
			for (int i = 0; i <= 6; i++) {
				for (int j = i; j <= 6; j++) {
					mChessBoard.mAllBlock[k++] = i;
					mChessBoard.mAllBlock[k++] = j;
				}
			}
			// xáo bài 100 trận
			int time = 0, choice1, choice2, tmp;
			while (time < 100) {
				choice1 = (int) (Math.random() * 56);
				choice2 = (int) (Math.random() * 56);
				// mỗi block có 2 số nên phải swap cả 2
				if (choice1 % 2 != 0)
					choice1--;
				if (choice2 % 2 != 0)
					choice2--;
				tmp = mChessBoard.mAllBlock[choice1];
				mChessBoard.mAllBlock[choice1] = mChessBoard.mAllBlock[choice2];
				mChessBoard.mAllBlock[choice2] = tmp;
				tmp = mChessBoard.mAllBlock[++choice1];
				mChessBoard.mAllBlock[choice1] = mChessBoard.mAllBlock[++choice2];
				mChessBoard.mAllBlock[choice2] = tmp;
				time++;
			}
			// chia lần lượt cho mọi người
			Player curPlayer;
			int cur = 0, luot = 0, curBlock = 0;
			while (luot < 7) {
				curPlayer = MainActivity.mServer.getRoom().getLeftPlayer(cur);
				if (curPlayer.isServer()) {
					HashMap<String, Integer> map = new HashMap<String, Integer>();
					map.put("1st", mChessBoard.mAllBlock[curBlock++]);
					map.put("2nd", mChessBoard.mAllBlock[curBlock++]);
					map.put("status", 1);
					mChessBoard.mTakenBlocks.add(map);
					handler.post(new Runnable() {

						@Override
						public void run() {
							arrBlockOnHand[mNumberBlockOnHand]
									.setBackgroundResource(getBlockImage(mChessBoard.mTakenBlocks
											.get(mNumberBlockOnHand++)));
						}
					});
				} else {
					curPlayer.sendMessage("TAKEBLOCK_"
							+ mChessBoard.mAllBlock[curBlock++] + ":"
							+ mChessBoard.mAllBlock[curBlock++]);
				}
				curPlayer = MainActivity.mServer.getRoom().getRightPlayer(cur);
				curPlayer.sendMessage("TAKEBLOCK_"
						+ mChessBoard.mAllBlock[curBlock++] + ":"
						+ mChessBoard.mAllBlock[curBlock++]);
				cur++;
				if (cur >= MainActivity.mServer.getRoom().getNumberOfPlayer() / 2) {
					cur = 0;
					luot++;
				}
			}

		}
	}

	class ClientDomino extends Thread {

		@Override
		public void run() {
			try {
				while (!isInterrupted()) {
					String[] stream = MainActivity.mClient.getInput()
							.readLine().split("_");
					String code = stream[0];
					String data = stream[1];
					switch (code) {
					case "CAN":
						handler.post(new Runnable() {

							@Override
							public void run() {
								mChessBoard.mCanPlay = true;
							}
						});
						break;
					case "TAKEBLOCK":
						String[] dataSplited = data.split(":");
						HashMap<String, Integer> map = new HashMap<String, Integer>();
						map.put("1st", Integer.parseInt(dataSplited[0]));
						map.put("2nd", Integer.parseInt(dataSplited[1]));
						map.put("status", 1);
						mChessBoard.mTakenBlocks.add(map);
						handler.post(new Runnable() {
							@Override
							public void run() {
								arrBlockOnHand[mNumberBlockOnHand]
										.setBackgroundResource(getBlockImage(mChessBoard.mTakenBlocks
												.get(mNumberBlockOnHand++)));
							}
						});
						break;
					case "PLAY":
						updateData = data;
						handler.post(new Runnable() {
							@Override
							public void run() {
								mChessBoard.putOnChessBoard(updateData);
							}
						});
						break;
					case "FIRSTPLAY":
						updateData = data;
						handler.post(new Runnable() {
							@Override
							public void run() {
								mChessBoard
										.putFirstBlockOnChessBoard(updateData);
							}
						});
						break;
					case "LOSE":
						handler.post(new Runnable() {
							@Override
							public void run() {
								Toast.makeText(DominoActivity.this,
										"Bạn đã thua :(", Toast.LENGTH_LONG)
										.show();
							}
						});
						this.interrupt();
						break;
					case "COUNT":
						MainActivity.mClient.getOutput().println(
								mChessBoard.countPoint());
						break;
					case "WIN":
						handler.post(new Runnable() {
							@Override
							public void run() {
								Toast.makeText(DominoActivity.this,
										"Bạn đã thắng điểm số thấp hơn ^^!",
										Toast.LENGTH_LONG).show();
							}
						});

						mClientDomino.interrupt();
						break;
					}
				}
			} catch (Exception e) {
				Log.i("topcbl", "Client lỗi: " + e.getMessage());
			}
		}

	}
}